<?php
/*
 * Ruffy.php - Main file for the Ruffy IRC Bot
 * Written by Nick Markwell
 *
 * Part of the Ruffy IRC Bot
 * http://rockermono.nonlogic.org/projects/
 *
 * Ruffy is slightly based on the connection portions of the Xando/BONO IRC Bots
 *
 */

error_reporting(E_ERROR | E_WARNING | E_PARSE); // This will NOT report uninitialized variables ,etc

include("ruffy.config.php");

$floodIgnores=Array();

$startTime=microtime(true);

$version=6.0;
$verStr=(string)$version;
if(!stristr($verStr,".")){
  $version=number_format($version,1);
  $verStr=(string)$version;
}
$useColors=true;
$commandSent=false;
$allCommands=Array();
$antiFloodGlobal=0;
$antiFloodGlobalTime=time();
$antiFlood=Array();
$antiFloodTime=Array();

function command($command,$level=1){
  global $buffer,$channel,$comchar,$messageA,$nickname,$sender,$currentCommand,$senderHost,$after_param;
  global $levels,$commandSent,$allCommands;
  $lsenderHost=strtolower($senderHost);
  $lsenderHost=strtolower($senderHost);
  if(!$levels[$lsenderHost]){
	   $access=1;
  } else {
     $access=$levels[$lsenderHost];
  }
  if(!in_array(strtolower($command),$allCommands)){
    $allCommands[]=strtolower($command);
  }
  if($comchar){
    if(stristr($buffer,"PRIVMSG $channel :".$comchar.$command)){
      $CommandRequested=true;
    }
  } else if(stristr($messageA[0],$nickname)){
    $CommandRequested=true;
  } else {
    $CommandRequested=false;
  }
  if($CommandRequested){
    if(trim($messageA[1])==trim($command)){
      if($access>=$level){
        $commandSent=true;
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }
}

function updateAccess(){
  global $levels;
  $accessFile=fopen("data/access.dat","w");
  fwrite($accessFile,serialize($levels));
  fclose($accessFile);
}

include("controls/memory.php");
include("controls/common.php");

if(!empty($_SERVER['argv'][1])){
  $network=$_SERVER['argv'][1];
  if(stristr($network,":")){
    $networkA=explode(":",$network);
    $network=$networkA[sizeOf($networkA)-2];
    $port=$networkA[sizeOf($networkA)-1];
  }
} else {
  $network="irc.freenode.net";
}

file_put_contents("data/ruffy-$network.pid", getmypid());

// The Access levels Array, probably wise to not edit it directly
if(file_exists("data/access.dat")){
  $levels=unserialize(file_get_contents("data/access.dat"));
}

if(!empty($_SERVER['argv'][2])){
  if(stristr($_SERVER['argv'][2],";")){
    $channels=explode(';',$_SERVER['argv'][2]);
  } else {
    $channels=Array($_SERVER['argv'][2]);
  }
} else if($config['channels']) {
  $channels=$config['channels'];
} else {
  $channels=$defaultChannels;
}

if(!empty($_SERVER['argv'][3])){
  if(!empty($prefix)){
    $prefix=$_SERVER['argv'][3];
  }
}
$allCommands="";
$originalNick=$nickname;
$checkWhois=false;
$ghosted=false;

function SendCommand ($cmd,$silent=false)
{
    $cmd=$cmd."\r\n";
    if(strlen($cmd)>512){
      $cmd=substr($cmd,0,500)." [abbr]";
      $cmd=str_replace("\r","",$cmd);
      $cmd=str_replace("\n","",$cmd);
      $cmd.="\r\n";
    }
    global $server,$joined,$antiFlood,$sender,$senderHost,$antiFloodGlobal,$floodIgnores;
    $lsender=strtolower($sender);
    $lsenderHost=strtolower($senderHost);
    if(!$floodIgnores[$lsender]){
      $floodIgnores[$lsender]=0;
    }
    if(!empty($cmd)){
      if(!$antiFlood[$lsender]){
        $antiFlood[$lsender]=0;
      }
      if($antiFlood[$lsender]<2 and $antiFloodGlobal<5){
        fwrite($server['SOCKET'], $cmd, strlen($cmd)); //sends the command to the server
        if(!$silent){
          echo "[SEND] ".str_replace(chr(7),"",$cmd);
        } else {
          echo "[SEND] (Command hidden)\r\n";
        }
      }
      if($floodIgnore[$lsender]>4){
        $levels[$lsender]=0;
        $levels[$lsenderHost]=0;
        updateAccess();
      }
      if(($joined) && (!$silent)){
          $antiFlood[$lsender]++;
          //$antiFloodGlobal++;
      }
    }
}
function pm($text, $chan = "", $silent = false){
	global $channel;
	if(empty($chan)) $chan = $channel;
	if(empty($text)) return false;
	SendCommand("PRIVMSG $chan :$text", $silent);
	return true;
}

while(true){

	if(!empty($nickname)){
		$server_host = $network;
		if(empty($port)){
			$server_port=6667;
		} else {
			$server_port=$port;
		}

		$joined=false;

    $server = array();
    $server['SOCKET'] = fsockopen($server_host, $server_port, $errno, $errstr, 2);
    if($server['SOCKET'])
    {
          SendCommand("NICK $nickname");
          SendCommand("USER $nickname USING PHP IRC");
        while(!feof($server['SOCKET']))
        {
            $server['READ_BUFFER'] = fgets($server['SOCKET'], 1024); //get a line of data from the server
            // this next line disables the beep [x07] character from beeping your computer :)
            $server['READ_BUFFER']=str_replace(chr(7),"",$server['READ_BUFFER']);
							$server['READ_BUFFER']=trim($server['READ_BUFFER'],"  ");
            if(!empty($server['READ_BUFFER'])){
              echo "[RECEIVE] ".$server['READ_BUFFER']; //display the recived data from the server
            }

            $commandSent=false;
            $allCommands=Array();
            $buffer=$server['READ_BUFFER'];
            $buffer=str_replace("\r","",$buffer);
            $buffer=str_replace("\n","",$buffer);
						$bufferA = explode(" ", $buffer);

						$message = substr($buffer, strlen(":".$bufferA[0]." ".$bufferA[1]." ".$bufferA[2]." "));
						if(substr($message, 0, 1) == ":") $message = substr($message, 1);
						$messageA = explode(" ", $message);

						$senderWhole = substr($bufferA[0], 1, strlen($bufferA[0])-1);
						$sender = substr($senderWhole, 0, strpos($senderWhole, "!"));
						$senderHost = substr($senderWhole, strpos($senderWhole, "@")+1);

            $channel = $bufferA[2];
            $method=$bufferA[1];

            $param=substr($buffer, strlen(implode(" ",Array($bufferA[0], $bufferA[1], $bufferA[2], $bufferA[3], $bufferA[4], ""))));
            $paramA=explode(" ", $param);
            if(strtolower($channel)==strtolower($nickname)){
              $channel=$sender;
            }

            if($bufferA[1]=="376" OR $bufferA[1]=="422"){
								SendCommand("MODE $nickname +B");
                SendCommand("PRIVMSG Nickserv :identify ".$password[strtolower($network)],true);
                SendCommand("JOIN ".implode(",",$channels));
								$joined=true;
            }

            if($bufferA[1]=="433"){
              $nickname=$nickname."_";
              SendCommand("NICK $nickname");
            }

            if($joined){
							foreach(dirlist("./modules/",true) as $module){
								if(substr($module,strlen($module)-4)==".php" and substr($module,strlen("./modules/"),1)!="_"){
									$moduleText=file_get_contents($module);
									$moduleText=substr($moduleText,5,strlen($moduleText)-7);
									try{
										eval($moduleText);
									} catch(Exception $e){
										//echo "\n\n".$e->getMessage()."\n\n";
										echo "\nError in $module\n";
									}
									//include($module);
								}
							}
							if(command("help")){
								SendCommand("NOTICE $sender :Current commands: ".implode(", ",$allCommands));
							}
						}

            $uFloodTime=time();
            $uFloodTime-=10;
            $lsender=strtolower($sender);
            if(!is_array($antiFlood)){
              $antiFlood=Array();
            }
            if(!is_array($antiFloodTime)){
              $antiFloodTime=Array();
            }
            if(!$antiFloodTime[$lsender]){
              $antiFloodTime[$lsender]=time();
            }
            if($antiFloodTime[$lsender]<=$uFloodTime){
              if($antiFlood[$lsender]>0){
                $antiFlood[$lsender]--;
              } else {
                $antiFloodTime[$lsender]=time();
              }
            }
            if($antiFloodGlobalTime<=$uFloodTime){
              if($antiFloodGlobal>0){
                $antiFloodGlobal--;
              }
            }

            if(substr($server['READ_BUFFER'], 0, 6) == "PING :"){
              SendCommand("PONG :".substr($server['READ_BUFFER'], 6)."\r\n");
            }
            flush();
       }
    }
}

// no instant reconnects! wait 10 seconds so it wont freeze your computer or get klined 
sleep(10);

}
?>
